﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Spectrum
{
    /// <summary>
    /// 时间参数
    /// </summary>
    public class AccelParam
    {
        /// <summary>
        /// 时间
        /// </summary>
        public float Time { set; get; }

        /// <summary>
        /// 加速度
        /// </summary>
        public float Accel { set; get; }

        /// <summary>
        /// 线性插值
        /// </summary>
        /// <param name="paramJ"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public AccelParam Interpolation(AccelParam paramJ, float time)
        {
            //求得斜率
            float slope = (paramJ.Accel - this.Accel) / (paramJ.Time - this.Time);
            //线性插值求得加速度
            float accel = slope * (time - this.Time) + this.Accel;
            //返回参数
            return new AccelParam
            {
                Time = time,
                Accel = accel,
            };
        }

        /// <summary>
        /// 空的构造函数
        /// </summary>
        public AccelParam()
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="Time"></param>
        public AccelParam(float time)
        {
            this.Time = time;
        }
    }

    /// <summary>
    /// 加速度激励时程
    /// </summary>
    public class AccelSet
    {
        #region Variables

        /// <summary>
        /// 初始的加速度时程曲线
        /// </summary>
        private List<AccelParam> OriginAccelList_ { set; get; }

        /// <summary>
        /// 目标时程曲线
        /// </summary>
        private List<AccelParam> TargetAccelList_ { set; get; }

        /// <summary>
        /// 目标加速度时间间隔
        /// </summary>
        private float TargetAccelTimeInterval { set; get; }

        /// <summary>
        /// 目标加速度时间最大值
        /// </summary>
        private float TargetAccelTimeLength { set; get; }

        #endregion

        #region Properties

        /// <summary>
        /// 获得时程最大时间
        /// </summary>
        public float OriginAccelMaxTime
        {
            get
            {
                //初始化
                double tmax = new double();
                //遍历时间数据
                this.OriginAccelList_.ForEach(param => tmax = Math.Max(tmax, param.Time));
                //返回最大时间
                return (float)tmax;
            }
        }

        #endregion

        /// <summary>
        /// 系数初始加速度时程获得目标加速度时程
        /// </summary>
        public List<AccelParam> GetSpraseAccelHist(float dt, float length)
        {
            //响应是否为空
            if (this.OriginAccelList_.Count == 0) return this.TargetAccelList_;
            //初始化
            this.TargetAccelTimeInterval = dt;
            this.TargetAccelTimeLength = length == -1 ? this.OriginAccelMaxTime :
                length;
            //决定数据点数据
            int StepNumber = (int)(this.TargetAccelTimeLength /
                this.TargetAccelTimeInterval) + 1;
            //初始加速度时程排序
            this.OriginAccelList_.OrderBy(param => param.Time);
            //实例化
            this.TargetAccelList_ = new List<AccelParam>(StepNumber);
            //索引符号初始化(加速时程稀疏效果)
            int searchIndex = new int();
            //添加数据
            for (int step = 0; step < StepNumber; step++)
            {
                //确定时刻
                var time = step * this.TargetAccelTimeInterval;
                //判断是否越界
                if (searchIndex + 1 >= this.OriginAccelList_.Count)
                {
                    this.TargetAccelList_.Add(new AccelParam(time));
                    continue;
                }
                //记录前一步的值
                var preAccel = this.OriginAccelList_[searchIndex];
                var postAccel = this.OriginAccelList_[searchIndex + 1];
                //寻找区间
                while (time > postAccel.Time)
                {
                    //越界
                    if (++searchIndex + 1 >= this.OriginAccelList_.Count)
                        break;
                    //确定新的迭代参数
                    preAccel = postAccel;
                    postAccel = this.OriginAccelList_[searchIndex + 1];
                }
                //不越界直接进行线性插值
                this.TargetAccelList_.Add(preAccel.Interpolation(postAccel, time));
            }
            return this.TargetAccelList_;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public AccelSet()
        {
            this.OriginAccelList_ = new List<AccelParam>();
            this.TargetAccelList_ = new List<AccelParam>();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="originAList"></param>
        /// <param name="dt"></param>
        /// <param name="length"></param>
        public AccelSet(List<AccelParam> originAList)
        {
            this.OriginAccelList_ = originAList;
        }
    }
}
